package com.jhh.pay.center.actor;

import akka.actor.ActorRef;
import akka.pattern.Patterns;
import akka.util.Timeout;
import com.alibaba.fastjson.JSON;
import com.jhh.pay.center.api.data.PayRequest;
import com.jhh.pay.center.cfg.GlobalConfigProperties;
import com.jhh.pay.center.cfg.SpringAppContext;
import com.jhh.pay.center.model.*;
import com.jhh.pay.center.search.DocTransformer;
import com.jhh.pay.center.service.ExistChecker;
import com.jhh.pay.center.service.OrderService;
import com.jhh.pay.center.service.cloud.message.TradeResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import scala.concurrent.Await;
import scala.concurrent.Future;
import scala.concurrent.duration.Duration;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author tangxd
 * @Description: 打款ACTOR
 * @date 2017/12/6
 */
@Service("PayActor")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Slf4j
public class PayActor extends BaseJhhActor {

    @Autowired
    private OrderService orderService;

    @Autowired
    private ExistChecker existChecker;

    @Autowired
    private DocTransformer<TradeState, OrderState> stateTransformer;

    private ActorRef sourceSender;

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .match(PayRequest.class, r -> {

                    /**
                     * 保存原sender
                     */
                    sourceSender = sender();

                    Order order = new Order();
                    order.setActiveQuery(r.isActiveQuery());
                    order.setAppId(r.getAppId());
                    order.setBankCard(r.getBankInfo().getBankCard());
                    order.setBankMobile(r.getBankInfo().getBankMobile() != null ? r.getBankInfo().getBankMobile() : "");
                    order.setPersonalName(r.getBankInfo().getPersonalName());
                    order.setBankNo(r.getBankInfo().getBankNo() != null ? r.getBankInfo().getBankNo() : "");
                    order.setExtension(JSON.toJSONString(r.getExtension()));
                    order.setChannels(JSON.toJSONString(r.getChannels()));
                    order.setMoney(r.getMoney());
                    order.setNotifyUrl(r.getNotifyUrl());
                    order.setOrderNo(r.getOrderNo());
                    order.setOrderTime(new Date(r.getOrderTime() * 1000L));
                    order.setType(OrderType.PAY);
                    order.setActorPath(self().path().toSerializationFormat());

                    /**
                     * 选择支付通道
                     */
                    ActorRef channelSelectActor = context().actorOf(SpringAppContext.props("PayChannelSelectorActor"));
                    Future<Object> future = Patterns.ask(channelSelectActor, order, new Timeout(Duration.apply(config.getActorProcessTimeout(), TimeUnit.SECONDS)));
                    Object resp = Await.result(future, Duration.apply(config.getActorProcessTimeout(), TimeUnit.SECONDS));
                    if (resp instanceof TradeResult) {
                        sender().tell(resp, self());
                        context().stop(self());
                        return;
                    }
                    PayChannel channel = (PayChannel) resp;
                    order.setChannelId(channel.getId());

                    try {
                        boolean ok = orderService.save(order);
                        if (!ok) {
                            sender().tell(TradeResult.create(TradeState.ERROR, "SYS:PAY:0001", "保存订单错误"), self());
                            context().stop(self());
                            return;
                        }
                        existChecker.add("PAY-ORDERS-" + r.getAppId(), r.getOrderNo());
                    } catch (Exception e) {
                        log.error(e.getMessage(), e);
                        sender().tell(TradeResult.create(TradeState.ERROR, "SYS:PAY:0002", "保存订单错误"), self());
                        context().stop(self());
                        return;
                    }

                    ActorRef channelActor = context().actorOf(SpringAppContext.props("PayTradeActor"));
                    TradeData pt = new TradeData();
                    pt.setAsync(r.isAsync());
                    pt.setOrder(order);
                    channelActor.tell(pt, self());
                })
                .match(TradeResult.class, r -> {
                    Order order = orderService.get(r.getSid());
                    if (null == order) {
                        log.error("订单不存在" + r.getSid());
                        sender().tell(TradeResult.create(TradeState.ERROR, "SYS:PAY:0003", "保存订单错误", r.getSid(), r.getChannelId()), self());
                        context().stop(self());
                        return;
                    }
                    order.setState(stateTransformer.transform(r.getState()));
                    order.setLastResp(JSON.toJSONString(r));
                    order.setLastRespTime(new Date());
                    order.setChannelId(r.getChannelId());
                    if (r.getState() == TradeState.SUCCESS) {
                        order.setSuccessTime(new Date());
                    }
                    try {
                        orderService.update(order);
                    } catch (Exception e) {
                        log.error(e.getMessage(), e);
                        sourceSender.tell(TradeResult.create(TradeState.ERROR, "SYS:PAY:0004", "保存订单错误", r.getSid(), r.getChannelId()), self());
                    }
                    sourceSender.tell(r, self());
                    context().stop(self());
                })
                .build();
    }

    @Override
    public void unhandled(Object message) {
        super.unhandled(message);
        log.warn("未处理消息", message);
    }
}
